package rename_column

import (
	"fmt"

	"github.com/example-user/go-pocket-etl/pkg/core"
	"github.com/example-user/go-pocket-etl/pkg/factory"
)

// init 实现了组件的自注册。
func init() {
	factory.RegisterProcessor("rename_column", NewProcessor)
}

// Processor 实现了 core.Processor 接口，用于重命名记录中的一个或多个列。
// 这个处理器常用于统一来自不同数据源的列名，或使列名更具可读性。
type Processor struct {
	mapping map[string]string // 存储列名映射关系，键是旧列名，值是新列名。
}

// NewProcessor 是 rename_column.Processor 的构造函数，由工厂调用。
func NewProcessor() core.Processor {
	return &Processor{}
}

// Open 从配置中解析列的重命名映射。
//
// 它期望配置中有一个名为 `mapping` 的键，其值为一个从旧列名到新列名的映射。
// YAML 配置示例:
//   - type: rename_column
//     params:
//     mapping:
//     "user_email": "email"
//     "created_dt": "creation_date"
func (p *Processor) Open(config map[string]interface{}) error {
	mappingVal, ok := config["mapping"]
	if !ok {
		return fmt.Errorf("rename_column processor: config is missing required key 'mapping'")
	}

	// YAML 解析器会将 map 解析为 map[interface{}]interface{}，这里需要进行类型转换。
	mapping, ok := mappingVal.(map[interface{}]interface{})
	if !ok {
		return fmt.Errorf("rename_column processor: 'mapping' must be a map (key-value pairs)")
	}

	if len(mapping) == 0 {
		return fmt.Errorf("rename_column processor: 'mapping' cannot be empty")
	}

	p.mapping = make(map[string]string)
	for k, v := range mapping {
		kStr, okK := k.(string)
		vStr, okV := v.(string)
		if !okK || !okV {
			return fmt.Errorf("rename_column processor: 'mapping' keys and values must all be strings")
		}
		p.mapping[kStr] = vStr
	}

	return nil
}

// Process 对记录进行处理，根据映射重命名指定的列。
//
// 如果在映射中指定的旧列名不存在于记录中，它将被静默忽略。
//
// **[CRITICAL] 警告：命名冲突与数据丢失风险**
// 当前实现通过遍历输入记录来构建一个新记录。如果一个重命名操作（例如 `A` -> `B`）
// 与一个已存在且未被重命名的列（`B`）发生冲突，那么输出记录中 `B` 的最终值将
// 取决于 Go 语言不确定的 map 迭代顺序。这可能导致不可预测的数据丢失。
//
// **强烈建议**：确保配置的 `mapping` 中，新的列名不会与任何未被重命名的现有列名冲突。
func (p *Processor) Process(record core.Record) (core.Record, error) {
	newRecord := make(core.Record, len(record))

	for oldKey, value := range record {
		// 检查这个 key 是否在我们的重命名映射中。
		if newKey, ok := p.mapping[oldKey]; ok {
			// 如果是，使用新的 key。
			newRecord[newKey] = value
		} else {
			// 如果不是，则保留原样。
			newRecord[oldKey] = value
		}
	}

	return newRecord, nil
}

// Close 是一个无操作（no-op）方法，因为 rename_column 处理器是无状态的，不需要在处理结束后清理任何资源。
func (p *Processor) Close() error {
	return nil
}
